🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / data / src / commonMain / kotlin / org / meshtastic / core / data / ai / RateLimiter.kt
Displaying Raw • Download
core/data/src/commonMain/kotlin/org/meshtastic/core/data/ai/RateLimiter.kt 3ca87fa0323214c7204c9d37acfe9d4b6ab6ea8b (3ca87fa0) Text, 2.69 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.data.ai
Tff7b72import T7ee787kotlinx.coroutines.sync.Mutex
Tff7b72import T7ee787kotlinx.coroutines.sync.withLock
Tff7b72import T7ee787org.koin.core.annotation.Single
Tff7b72import T7ee787kotlin.time.Clock
Tff7b72import T7ee787kotlin.time.Duration.Companion.seconds
Tff7b72import T7ee787kotlin.time.Instant
T8b949e/**
* Sliding-window rate limiter for AI-triggered operations.
*
* Tracks the last [maxCalls] invocation timestamps. A new call is permitted only if fewer than [maxCalls] occurred
* within the [windowDuration]. This prevents aggregate AI traffic from flooding the mesh network.
*
* The limiter is intentionally process-scoped and global so concurrent AI surfaces share a single airtime budget.
*/
Tf0883e@Single
Tff7b72class T56d364RateLimiterTb4b4b4(Tff7b72private Tff7b72val Te6edf3clockTb4b4b4: Te6edf3ClockTb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3mutex Tff7b72= Te6edf3MutexTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3timestamps Tff7b72= Te6edf3ArrayDequeTff7b72<Te6edf3InstantTff7b72>Tb4b4b4(Te6edf3MAX_CALLSTb4b4b4)
T8b949e/**
* Attempt to acquire a permit for one invocation.
*
* @return [RateLimitResult.Permitted] if under the limit, or [RateLimitResult.Limited] with the number of seconds
* until a slot frees up.
*/
Tff7b72suspend Tff7b72fun Td2a8fftryAcquireTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3RateLimitResult Tff7b72= Te6edf3mutexTb4b4b4.Te6edf3withLock Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3clockTb4b4b4.Te6edf3nowTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3windowStart Tff7b72= Te6edf3now Tff7b72- Te6edf3WINDOW_DURATION
T8b949e// Evict timestamps outside the window
Tff7b72while Tb4b4b4(Te6edf3timestampsTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3timestampsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4) Tff7b72<Tff7b72= Te6edf3windowStartTb4b4b4) Tb4b4b4{
Te6edf3timestampsTb4b4b4.Te6edf3removeFirstTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72return Tff7b72if Tb4b4b4(Te6edf3timestampsTb4b4b4.Te6edf3size Tff7b72< Te6edf3MAX_CALLSTb4b4b4) Tb4b4b4{
Te6edf3timestampsTb4b4b4.Te6edf3addLastTb4b4b4(Te6edf3nowTb4b4b4)
Te6edf3RateLimitResultTb4b4b4.Te6edf3Permitted
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72val Te6edf3oldestInWindow Tff7b72= Te6edf3timestampsTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3retryAfter Tff7b72= Tb4b4b4(Tb4b4b4(Te6edf3oldestInWindow Tff7b72+ Te6edf3WINDOW_DURATIONTb4b4b4) Tff7b72- Te6edf3nowTb4b4b4)Tb4b4b4.Te6edf3inWholeSecondsTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4) Tff7b72+ T79c0ff1
Te6edf3RateLimitResultTb4b4b4.Te6edf3LimitedTb4b4b4(Te6edf3retryAfterSeconds Tff7b72= Te6edf3retryAfterTb4b4b4.Te6edf3coerceAtLeastTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3MAX_CALLS Tff7b72= T79c0ff5
Tff7b72val Te6edf3WINDOW_DURATION Tff7b72= T79c0ff6T79c0ff0.Te6edf3seconds
Tb4b4b4}
Tb4b4b4}
Tff7b72sealed Tff7b72class T56d364RateLimitResult Tb4b4b4{
Tff7b72data Tff7b72object T56d364Permitted Tb4b4b4: Te6edf3RateLimitResultTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364LimitedTb4b4b4(Tff7b72val Te6edf3retryAfterSecondsTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4: Te6edf3RateLimitResultTb4b4b4(Tb4b4b4)
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.05s